home *** CD-ROM | disk | FTP | other *** search
- structure KnownFiddle : sig val fiddle: CPS.function -> CPS.function end =
-
- (* This is a transformation of the CPS to be made just before the
- closure phase. If there is a FIX defining function g,
- where the body of g calls the known function f defined outside of the
- FIX, then we will add to the list of functions defined by the
- fix an inverse-eta-reduction of f.
-
- Thus:
-
-
- e as FIX([ ... (g,_, ... APP(f,...)...), ... ], ...) where f free in e
-
- rewrites to
-
- FIX([ ... (g,_, ... APP(f',...) ...), ..., (f',vl',APP(f,vl')) ], ...)
-
- The purpose of this is to improve the code generated by the
- closure transformation. In particular, if the APP(f,...) were in
- a BRANCH or other control flow such that g did not always execute
- it, then the closure module would normally make all the free variables
- of f into extra arguments of g (normally by fetching them from
- an appropriate closure). This way, fetching the free variables of
- f from the closure is delayed until the actual call of f, which is
- a win if f is not always called.
-
- *)
-
- struct
-
- open CPS Access
-
- fun pass1 cexp : lvar -> lvar list =
- (* The result of pass1 is a map showing, for each FIX labelled
- by the name of its first-defined function, the set of
- functions (known or otherwise) in function position within
- the bodies of all functions defined by that FIX.
- *)
- let exception Amap
- val amap : lvar list Intmap.intmap = Intmap.new(32,Amap)
- val note_applied = Intmap.add amap
- val rec applied =
- fn APP(VAR v,args) => [v]
- | APP _ => []
- | SWITCH(v,c,l) => SortedList.foldmerge(map applied l)
- | RECORD(_,l,w,ce) => applied ce
- | SELECT(_,v,w,ce) => applied ce
- | OFFSET(_,v,w,ce) => applied ce
- | SETTER(_,vl,e) => applied e
- | LOOKER(_,vl,w,e) => applied e
- | ARITH(_,vl,w,e) => applied e
- | PURE(_,vl,w,e) => applied e
- | BRANCH(_,vl,c,e1,e2) => SortedList.merge(applied e1, applied e2)
- | FIX(nil,e) => applied e
- | FIX(fl as (f,_,_)::_, e) =>
- let val body_applied =
- SortedList.foldmerge(map (fn (f,vl,b) => applied b) fl)
- in note_applied (f, body_applied);
- SortedList.merge(body_applied, applied e)
- end
- in applied cexp;
- Intmap.map amap
- end
-
- fun fiddle (func,args,cexp) =
- let open IntmapF
-
- val applies = pass1 cexp
-
- fun rewrite_with (rename_map,knowns) =
- let val rename = IntmapF.lookup rename_map
- val rec rewrite =
- fn e as APP(VAR v,args) => (APP(VAR(rename v),args)
- handle IntmapF => e)
- | e as APP _ => e
- | SWITCH(v,c,l) => SWITCH(v,c,map rewrite l)
- | RECORD(k,l,w,ce) => RECORD(k,l,w, rewrite ce)
- | SELECT(i,v,w,ce) => SELECT(i,v,w, rewrite ce)
- | OFFSET(i,v,w,ce) => OFFSET(i,v,w, rewrite ce)
- | SETTER(p,vl,e) => SETTER(p,vl, rewrite e)
- | LOOKER(p,vl,w,e) => LOOKER(p,vl,w, rewrite e)
- | ARITH(p,vl,w,e) => ARITH(p,vl,w, rewrite e)
- | PURE(p,vl,w,e) => PURE(p,vl,w, rewrite e)
- | BRANCH(p,vl,c,e1,e2) => BRANCH(p,vl,c, rewrite e1, rewrite e2)
- | FIX(nil,e) => rewrite e
- | FIX(fl as (f,_,_)::_, e) =>
- let
- fun test(v::rest) = ((v, lookup knowns v) :: test rest
- handle IntmapF => test rest)
- | test nil = nil
-
- fun redefine (f,vl) =
- let val f'::vl' = map dupLvar (f::vl)
- in (f',vl',APP(VAR f, map VAR vl'))
- end
-
- val newdefs = map redefine (test (applies f))
-
- val rename_map' =
- fold (fn ((f',_,APP(VAR f, _)),m) => add(m,f,f'))
- newdefs
- rename_map
-
- val knowns' = fold (fn ((f,vl,b),kn) => add(kn,f,vl)) fl knowns
-
- fun rewrite_body(f,vl,b) =
- (f,vl, rewrite_with(rename_map',knowns') b)
-
- in FIX(map rewrite_body fl @ newdefs,
- rewrite_with(rename_map, knowns') e)
- end
- in rewrite
- end
-
- in (func, args, rewrite_with(empty,empty) cexp)
- end
-
-
- end
-
-